class Table {
    // 表格容器
    _tableContainer_
    _tableDom_ = null
    // 行列数
    _colCount_ = 7
    _rowCount_ = 7

    // 选中的单元格dom
    _selectedCells_ = []
    // 选中的单元格坐标
    _selectedIdx = []

    // 右键菜单
    _MenuEnum = {
        MERGE: "merge",
        ADD_COL: "add_col",
        ADD_ROW: "add_row"
    }
    _menuItems = [
        { text: "合并单元格", event: this._MenuEnum.MERGE },
        { text: "增加一列", event: this._MenuEnum.ADD_COL },
        { text: "增加一行", event: this._MenuEnum.ADD_ROW },
    ]

    constructor(tableContainer = "table-box",colCount,rowCount) {
        this._tableContainer_ = tableContainer
        this._colCount_ = colCount
        this._rowCount_ = rowCount
        setTimeout(() => {
            this._init()
        })
    }

    _init() {
        this.render()
        this.renderMenu()
        this._startListen()
    }

    renderMenu() {
        let menu = $("#menu")
        if(menu) {
            menu.remove()
        }
        let div = document.createElement("div")
        div.id = "menu"

        for (let menuItem of this._menuItems) {
            let childDiv = document.createElement("div")
            childDiv.className = "menu-item"
            childDiv.setAttribute("data-event", menuItem.event)
            childDiv.textContent = menuItem.text
            div.appendChild(childDiv)
        }

        $("#"+this._tableContainer_).append(div)
    }
    // 开始监听选中单元格
    _startListen() {
        const that = this
        // 表格选中
        $("#table").selectable({
            filter: "td",
            selected: (e, {selected: td}) => {
                const idx = $(td).attr("lang")
                that._selectedCells_.push(td)
                that._selectedIdx.push(idx)
            },
            selecting: () => {
                $("#menu").hide()
            },
            start: () => {
                $("#menu").hide()
                that._selectedCells_ = []
                that._selectedIdx = []
            },
            stop: () => {}
        });
        // 监听表格鼠标右键
        $("#table").on("contextmenu", "td", function (e) {
            e.preventDefault();
            let x = e.pageX;
            let y = e.pageY;

            let merge = $(`#menu .menu-item[data-event='${that._MenuEnum.MERGE}']`)
            // 选中数量只有1个，不显示合并菜单
            if(that._selectedCells_.length >= 2) {
                merge.show()
            } else {
                merge.hide()
            }

            $("#menu").show().css({
                left: x,
                top: y
            })
        })

        // 右键菜单事件
        $("#menu").on("click", function (e) {
            const target = e.target
            if(target.className !== "menu-item") return

            const eventType = target.dataset?.["event"]
            switch (eventType) {
                case that._MenuEnum.MERGE:
                    that.merge();
                    break;
                case that._MenuEnum.ADD_ROW:
                    that.addRows();
                    break;
                case that._MenuEnum.ADD_COL:
                    that.addCol();
                    break;
            }

            $(this).hide()
        })
    }

    /**
     * 表格合并
     */
    merge() {
        let {start,cols,rows} = this._calculateCells(this._selectedIdx)

        // 合并整列，行数超过两行，则删除第二行之后的全部，仅设置rowspan为1
        if(cols === this._colCount_ && rows >= 2) {
            rows = 1
        }

        // 合并整行，列数超过两列，则删除第二列之后的全部，仅设置colspan为1
        if(rows === this._rowCount_ && cols >= 2) {
            cols = 1
        }

        // 删除除开始的单元格以外的格子
        // 然后设置开始的单元格的colspan和rowspan
        this._selectedIdx.forEach(item => {
            if(item !== start) {
                $(`#table td[lang=${item}]`).remove()
            }
        })
        $(`#table td[lang=${start}]`).attr("colspan", cols).attr("rowspan", rows)
        $("#menu").hide()
    }

    /**
     * 辅助函数：计算选中单元格的行列数量,返回对应的行列数量，和起始坐标和终点坐标
     * @param {Array} cellPaths 选中单元格数组
     * @return {Object} {cols: 0, rows: 0, start: '', end: ''}
     */
    _calculateCells(cellPaths) {
        let cols = 0, rows = 0, start = "", end= "";
        if(cellPaths.length < 2) return {cols,rows,start,end}

        start = cellPaths[0]
        end = cellPaths[cellPaths.length - 1]

        let x = [], y = [];
        cellPaths.forEach(cell => {
            let tempX = cell.split('-')[0], // 列坐标
                tempY = cell.split("-")[1]; // 行坐标

            if(!x.includes(tempX)) {
                rows++
                x.push(tempX)
            }
            if(!y.includes(tempY)) {
                cols++
                y.push(tempY)
            }
        })

        return {cols,rows,start,end}
    }

    /**
     * 增加一列
     */
    addCol() {
        // 下标从0开始，列数量先不用+1
        let colIndex = this._colCount_
        this._colCount_++
        // 在每个tr末尾插入td
        $("#table tr").each((i, item) => {
            let rowIndex = $(item).attr("index")
            $(item).append(`<td lang="${rowIndex}-${colIndex}" index="${colIndex}" class="ui-selectee"></td>`)
        })
    }

    /**
     * 增加一行
     */
    addRows() {
        // 行数量先不用+1
        let rowIndex = this._rowCount_
        this._rowCount_++

        let tr = document.createElement("tr")
        tr.setAttribute("index", rowIndex)
        for (let i = 0; i < this._colCount_; i++) {
            let td = document.createElement("td")
            td.lang = `${rowIndex}-${i}`
            td.setAttribute("index", i)
            td.className = "ui-selectee"
            // td.textContent = `${rowIndex}-${i}`
            tr.appendChild(td)
        }
        // 在table末尾插入tr
        this._tableDom_.appendChild(tr)
    }

    // 清空表格
    clear() {
        $("#" + this._tableContainer_).empty()
        this._tableDom_ = null
    }
    // 渲染表格
    render() {
        this.clear()
        this._tableDom_ = document.createElement("table");
        this._tableDom_.style.borderCollapse = "collapse";
        this._tableDom_.className = "table"
        this._tableDom_.id = "table"

        for (let i = 0; i < this._rowCount_; i++) {
            let tr = document.createElement("tr");
            tr.setAttribute("index",i)
            for (let j = 0; j < this._colCount_; j++) {
                let td = document.createElement("td");
                let text = document.createTextNode(`${i}-${j}`);

                td.lang= `${i}-${j}`;//格子坐标
                td.setAttribute("index",j)
                // td.appendChild(text)
                tr.appendChild(td);
            }
            this._tableDom_.appendChild(tr);
        }
        $("#"+this._tableContainer_).append(this._tableDom_)
    }

    // 重置行列
    resetCells(cols,rows) {
        this._colCount_ = cols ?? this._colCount_
        this._rowCount_ = rows ?? this._rowCount_
        this.render()
        this.renderMenu()
        this._startListen()
    }
}

const table = new Table("fa",7,10)

let cols = 0,
    rows = 0;
function handleInput(dir, e) {
    const val = e.value
    if(dir === "col") {
        cols = val
    }
    if(dir === "row") {
        rows = val
    }
}
function onConfirm() {
    if(cols > 0 && rows > 0) {
        table.resetCells(cols,rows)
    }
}

function reset() {
    table.resetCells()
}